let vien
let board

function game2048(obj) {
    let prefix = obj.prefix
    let len = obj.len
    let size = obj.size
    let margin = obj.margin

    board = new Board(len)
    board.init()

    vien = new Vien(prefix, len, size, margin)
    vien.init(board.arr)

    board.generate()
    board.generate()

    document.addEventListener('keydown', function (event) {
        let moved = false;
        switch (event.key) {
            case 'ArrowLeft':
                moved = board.moveLeft();
                break;
            case 'ArrowRight':
                moved = board.moveRight();
                break;
            case 'ArrowUp':
                moved = board.moveUp();
                break;
            case 'ArrowDown':
                moved = board.moveDown();
                break;
        }

        if (moved) {
            board.generate(vien)
            vien.upVien(board.arr);
        }

        if (isGameOver(board.arr)) {
            alert("GAME OVER")
        }
    })

}

document.querySelector('#game_start').addEventListener('click', start)

function start() {
    document.querySelector("#score").innerText = 0
    document.querySelector('#game').innerHTML = ''
    board.init();
    vien.init()
    board.generate();
    board.generate();
}


function hasEmptyCell(arr) {
    for (let i = 0; i < arr.length; i++) {
        for (let j = 0; j < arr.length; j++) {
            if (arr[i][j] === 0) {
                return true; // 存在空格子
            }
        }
    }
    return false; // 没有空格子
}

// 检查是否还可以合并数字块
function canMerge(arr) {
    // 检查水平方向是否可以合并
    for (let i = 0; i < arr.length; i++) {
        for (let j = 0; j < arr.length - 1; j++) {
            if (arr[i][j] === arr[i][j + 1]) {
                return true; // 存在可以合并的数字块
            }
        }
    }

    // 检查垂直方向是否可以合并
    for (let j = 0; j < arr.length; j++) {
        for (let i = 0; i < arr.length - 1; i++) {
            if (arr[i][j] === arr[i + 1][j]) {
                return true; // 存在可以合并的数字块
            }
        }
    }

    return false; // 没有可以合并的数字块
}

// 判断游戏是否结束
function isGameOver(arr) {
    return !hasEmptyCell(arr) && !canMerge(arr);
}

class Vien {
    constructor(prefix, len, size, margin) {
        this.prefix = prefix
        this.len = len
        this.size = size
        this.margin = margin
    }

    getPos(n) {
        return this.margin + n * (this.size + this.margin);
    }

    init() {
        document.querySelector(`#${this.prefix}`).style.width = this.len * this.size + (this.len + 1) * this.margin + 'px'
        document.querySelector(`#${this.prefix}`).style.height = this.len * this.size + (this.len + 1) * this.margin + 'px'
        for (let x = 0; x < this.len; x++) {
            for (let y = 0; y < this.len; y++) {
                let div = document.createElement("DIV")
                div.classList.add(`${this.prefix}_container`)
                div.style.width = this.size + "px"
                div.style.height = this.size + "px"
                div.style.lineHeight = this.size + "px"
                div.style.top = this.getPos(x) + 'px'
                div.style.left = this.getPos(y) + 'px'
                document.querySelector(`#${this.prefix}`).append(div)
            }
        }
    }

    addNum(x, y, num) {
        let element = x * this.len + y
        let elementAll = document.querySelectorAll(`.${this.prefix}_container`)
        elementAll[element].classList.add(`${this.prefix}-num-${num}`)
        elementAll[element].innerText = num
    }

    upVien(arr) {
        document.querySelector(`#${this.prefix}`).innerHTML = ''; // 清空游戏板
        for (let i = 0; i < arr.length; i++) {
            for (let j = 0; j < arr.length; j++) {
                let value = arr[i][j];
                let tile = document.createElement('div');
                tile.classList.add(`${this.prefix}_container`)
                tile.classList.add(`${this.prefix}-num-${arr[i][j]}`);
                tile.style.width = this.size + "px"
                tile.style.height = this.size + "px"
                tile.style.lineHeight = this.size + "px"
                tile.style.top = this.getPos(i) + 'px'
                tile.style.left = this.getPos(j) + 'px'
                tile.textContent = value !== 0 ? value : ''; // 设置数字块的显示内容
                document.querySelector(`#${this.prefix}`).appendChild(tile); // 将数字块添加到游戏板容器中
            }
        }
    }

    updateScore(score) {
        const scoreElement = document.querySelector("#score");
        let oldScore = scoreElement.innerText * 1
        scoreElement.innerText = score + oldScore;
    }

}

class Board {
    constructor(len) {
        this.len = len
        this.arr = []
    }

    init() {
        let arr = []
        for (let x = 0; x < this.len; x++) {
            arr[x] = []
            for (let y = 0; y < this.len; y++) {
                arr[x][y] = 0
            }
        }
        this.arr = arr
    }


    generate() {
        let empty = []
        for (let x = 0; x < this.arr.length; x++) {
            for (let y = 0; y < this.arr[x].length; y++) {
                if (this.arr[x][y] === 0) empty.push({x: x, y: y})
            }
        }
        if (empty.length < 1) return false
        let pos = empty[Math.floor(Math.random() * (empty.length))]
        this.arr[pos.x][pos.y] = Math.random() > 0.5 ? 2 : 4
        vien.addNum(pos.x, pos.y, this.arr[pos.x][pos.y])
    }


    moveLeft() {
        let moved = false;
        for (let i = 0; i < this.arr.length; i++) {
            for (let j = 1; j < this.arr.length; j++) {
                if (this.arr[i][j] !== 0) {
                    let k = j - 1;
                    while (k >= 0 && this.arr[i][k] === 0) {
                        k--;
                    }
                    if (k >= 0 && this.arr[i][k] === this.arr[i][j]) {
                        // 合并数字块
                        this.arr[i][k] *= 2;
                        vien.updateScore(this.arr[i][k])
                        this.arr[i][j] = 0;
                        moved = true;
                    } else if (k + 1 !== j) {
                        // 移动数字块
                        this.arr[i][k + 1] = this.arr[i][j];
                        this.arr[i][j] = 0;
                        moved = true;
                    }
                }
            }
        }
        return moved;
    }

    moveRight() {
        let moved = false;
        for (let i = 0; i < this.arr.length; i++) {
            for (let j = this.arr.length - 2; j >= 0; j--) {
                if (this.arr[i][j] !== 0) {
                    let k = j + 1;
                    while (k < this.arr.length && this.arr[i][k] === 0) {
                        k++;
                    }
                    if (k < this.arr.length && this.arr[i][k] === this.arr[i][j]) {
                        // 合并数字块
                        this.arr[i][k] *= 2;
                        vien.updateScore(this.arr[i][k] )
                        this.arr[i][j] = 0;
                        moved = true;
                    } else if (k - 1 !== j) {
                        // 移动数字块
                        this.arr[i][k - 1] = this.arr[i][j];
                        this.arr[i][j] = 0;
                        moved = true;
                    }
                }
            }
        }
        return moved;
    }

// 向上移动和合并数字块
    moveUp() {
        let moved = false;
        for (let j = 0; j < this.arr.length; j++) {
            for (let i = 1; i < this.arr.length; i++) {
                if (this.arr[i][j] !== 0) {
                    let k = i - 1;
                    while (k >= 0 && this.arr[k][j] === 0) {
                        k--;
                    }
                    if (k >= 0 && this.arr[k][j] === this.arr[i][j]) {
                        // 合并数字块
                        this.arr[k][j] *= 2;
                        vien.updateScore(this.arr[i][k])
                        this.arr[i][j] = 0;
                        moved = true;
                    } else if (k + 1 !== i) {
                        // 移动数字块
                        this.arr[k + 1][j] = this.arr[i][j];
                        this.arr[i][j] = 0;
                        moved = true;
                    }
                }
            }
        }
        return moved;
    }

// 向下移动和合并数字块
    moveDown() {
        let moved = false;
        for (let j = 0; j < this.arr.length; j++) {
            for (let i = this.arr.length - 2; i >= 0; i--) {
                if (this.arr[i][j] !== 0) {
                    let k = i + 1;
                    while (k < this.arr.length && this.arr[k][j] === 0) {
                        k++;
                    }
                    if (k < this.arr.length && this.arr[k][j] === this.arr[i][j]) {
                        // 合并数字块
                        this.arr[k][j] *= 2;
                        vien.updateScore(this.arr[i][k])
                        this.arr[i][j] = 0;
                        moved = true;
                    } else if (k - 1 !== i) {
                        // 移动数字块
                        this.arr[k - 1][j] = this.arr[i][j];
                        this.arr[i][j] = 0;
                        moved = true;
                    }
                }
            }
        }
        return moved;
    }


}